/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package bridge;

import java.util.concurrent.Semaphore;

/**
 *
 * @author victor
 */
public class Bridge {

    private final Semaphore turnA = new Semaphore(1, true);
     private final Semaphore turnB = new Semaphore(1, true);
    private final Semaphore capacity = new Semaphore(3, true);
    private final Semaphore mutex = new Semaphore(1, true);
    private final Semaphore mutex2 = new Semaphore(1, true);
    private final Semaphore direction = new Semaphore(1);
    private final Semaphore cupos = new Semaphore(1, true);
    private char currentDirection = '\0';
    private int quota = 3;

    public Bridge() {
    }

    public void requestTurn(Habitant habitant) throws InterruptedException {

        //turn.acquire();
        switch (habitant.getDirection()) {
            case 'A':
                turnA.acquire();
                crossFromBtoA(habitant);
                turnA.release();
                break;
            case 'B':
                turnB.acquire();
                crossFromAtoB(habitant);
                turnB.acquire();
                break;
        }
        //turn.release();

//        if (currentDirection == '\0') {
//            direction.release();
//            turn.acquire();
//        } 
//        mutex.acquire();
//        if (currentDirection != habitant.getDirection()) {
//            //Printer.println(habitant + " is waiting");
//            mutex.release();
//            requestToChangeDirection(habitant);
//            //capacity.acquire();
//            acquireQuota();
//        } else {
////            mutex.acquire();
////            if (cupo == 0) {
////                Printer.println("No quota");
////                cupos.acquire();
////            }
////            mutex.release();
//            //capacity.acquire();
//            acquireQuota();
//        }

    }

    public void crossFromAtoB(Habitant habitant) throws InterruptedException {
        mutex.acquire();
        if (quota == 3 || habitant.getDirection() != currentDirection) {
            mutex.release();
            turnA.acquire();
            direction.acquire();
            requestToChangeDirection(habitant);
            turnA.release();
        }
        mutex.release();
        acquireQuota();
    }

    public void crossFromBtoA(Habitant habitant) throws InterruptedException {
        mutex.acquire();
        if (quota == 3 || habitant.getDirection() != currentDirection) {
            mutex.release();
            turnB.acquire();
            direction.acquire();
            requestToChangeDirection(habitant);
            turnB.release();
        }
        mutex.release();
        acquireQuota();
    }

    public void requestToChangeDirection(Habitant habitant) throws InterruptedException {
//        turn.acquire();
//        direction.acquire();
//        Printer.println(habitant + " is waiting to change direction");
        Printer.println("The brige is changing of direction to: " + habitant.getDirection());
        this.currentDirection = habitant.getDirection();

//        turn.release();
    }

    public void take(char direction) throws InterruptedException {
        // capacity.acquire();
//        turn.release();
    }

    public void acquireQuota() throws InterruptedException {
        mutex.acquire();
        capacity.acquire();
        quota--;
        mutex.release();
    }

    public void releaseQuota() throws InterruptedException {
        mutex.acquire();
        quota++;
        capacity.release();
        mutex.release();
    }

    public void exit() throws InterruptedException {

        releaseQuota();
        mutex.acquire();
        if (quota == 3) {
            mutex.release();
            direction.release();
            Printer.println("There is a quota");
            //cupos.release();
        }
        mutex.release();
        //turn.release();
    }

    public void croossing() {
    }

    public void release() {
        this.currentDirection = '\0';
        direction.release();

    }
}
